package io.jee.medusa.orm;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.Id;

import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.core.ResolvableType;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import org.springframework.util.StringUtils;

import io.jee.medusa.orm.condition.Condition;
import io.jee.medusa.orm.condition.CountCondition;
import io.jee.medusa.orm.pager.output.OutputPager;
import io.jee.medusa.orm.pager.support.ConditionSupport;

public class Hibernate4DaoSupport<T> extends HibernateDaoSupport implements DaoSupport<T> {

	private Class<?> entityClass;
	private String idFieldName;
	
	@Override
	protected void initDao() throws Exception {
		ResolvableType resolvableType = ResolvableType.forClass(getClass());
		Class<?>[] clazzs = resolvableType.getSuperType().resolveGenerics();
		entityClass = clazzs[0];
		
		//返回对象所表示的类或接口的所有可访问公共方法  
        Method[] methods = entityClass.getMethods();  
          
        for(Method method : methods){  
            Id meta = method.getAnnotation(Id.class);  
            if(meta!=null){  
            	idFieldName = method.getName().substring(3, 4).toLowerCase()+method.getName().substring(4);
            }  
        }  
		if(StringUtils.isEmpty(idFieldName)){
			Field[] fields = entityClass.getFields();
			for(Field field : fields){  
				Id meta = field.getAnnotation(Id.class);  
	            if(meta!=null){  
	            	idFieldName = field.getName();
	            }  
	        }
		}
		if(StringUtils.isEmpty(idFieldName)){
			idFieldName = "id";
		}
	}

	@Resource
	public void setSessionFactorySupport(SessionFactory sessionFactory) {
		super.setSessionFactory(sessionFactory);
	}
	
	@Override
	public Session getSession() {
		return super.currentSession();
	}
	
	@Override
	public Serializable save(T entity) {
		return super.getHibernateTemplate().save(entity);
	}
	
	@Override
	public void saveOrUpdate(T entity) {
		super.getHibernateTemplate().saveOrUpdate(entity);
	}
	
	@Override
	public void delete(T entity) {
		super.getHibernateTemplate().delete(entity);
	};

	@Override
	public int delete(String key, Object value) {
		String hql = "delete " + entityClass.getName() + " where " + key + " = :value";
		return super.currentSession().createQuery(hql).setParameter("value", value).executeUpdate();
	}
	
	@Override
	public int delete(String key, Object[] values) {
		String hql = "delete " + entityClass.getName() + " where " + key + " in (:value)";
		return super.currentSession().createQuery(hql).setParameterList("value", values).executeUpdate();
	}

	@Override
	public void update(T entity) {
		super.getHibernateTemplate().update(entity);
	}
	
	@Override
	public void update(T entity, LockMode lockMode) {
		super.getHibernateTemplate().update(entity, lockMode);
	}
	
	@Override
	public void update(String key, Object value, Serializable id) {
		String hql = "update " + entityClass.getName() + " set " + key + " = :" + key + " where "+idFieldName+" = :id";
		super.currentSession().createQuery(hql).setParameter(key, value).setParameter("id", id).executeUpdate();
	}
	
	@Override
	public void update(String key, Object value, Serializable[] ids) {
		// TODO Auto-generated method stub
		
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public T get(Serializable id) {
		return (T) super.getHibernateTemplate().get(entityClass, id);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public T get(Serializable id, LockMode lockMode) {
		return (T) super.getHibernateTemplate().get(entityClass, id, lockMode);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public T load(Serializable id) {
		return (T) super.getHibernateTemplate().load(entityClass, id);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public T unique(String key, Object value) {
		String hql = "select e from " + entityClass.getName() + " e where e." + key + " = :value";
		return (T) super.currentSession().createQuery(hql).setParameter("value", value).uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public T unique(String key, Object value, LockMode lockMode) {
		String hql = "select e from " + entityClass.getName() + " e where e." + key + " = :value";
		return (T) super.currentSession().createQuery(hql).setLockOptions(new LockOptions(lockMode)).setParameter("value", value).uniqueResult();
	}
	
	@Override
	public Serializable unique(String key, Object value, String fieldName) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public Serializable unique(String key, Object value, String fieldName, LockMode lockMode) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public Serializable maxId(LockMode lockMode) {
		return null;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> list(String key, Object value) {
		String hql = "select e from " + entityClass.getName() + " e where e." + key + " = :value";
		return super.currentSession().createQuery(hql).setParameter("value", value).list();
	}
	
	@Override
	public List<T> listJoin(String key, Object value, String joinField) {
		return null;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> list(String key, Object[] values) {
		String hql = "from " + entityClass.getName() + " e where e." + key + " in (:" + key + ")";
		return super.currentSession().createQuery(hql).setParameterList(key, values).list();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> list(int size) {
		Query query = super.currentSession().createQuery("from " + entityClass.getName()).setMaxResults(size);
		return query.list();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> listAll() {
		Query query = super.currentSession().createQuery("from " + entityClass.getName());
		return query.list();
	}

	@Override
	public long count(String key, Object value) {
		String hql = "select count(*) from " + entityClass.getName() + " e where e." + key + " = :value";
		return (Long) super.currentSession().createQuery(hql).setParameter("value", value).uniqueResult();
	}
	
	@Override
	public long count(String key, Object value, LockMode lockMode) {
		String hql = "select count(*) from " + entityClass.getName() + " e where e." + key + " = :value";
		return (Long) super.currentSession().createQuery(hql).setLockOptions(new LockOptions(lockMode)).setParameter("value", value).uniqueResult();
	}
	
	@Override
	public long countAll() {
		Query query = super.currentSession().createQuery("select count(*) from " + entityClass.getName());
		return (Long) query.uniqueResult();
	}
	
	@Override
	public <P extends ConditionSupport> OutputPager<T> page(P condition) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public Condition<T> condition() {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public CountCondition<T> countCondition() {
		// TODO Auto-generated method stub
		return null;
	}

}
